package struct.advanced.map;

/**
 * @author MAX
 * @version 1.0
 * @description 高级数据结构-基于二分搜索树的映射
 * @date 2022/1/17 10:20
 */
public class BstMap<K extends Comparable<K>, V> implements Map<K, V> {

    private Node root;
    private int size;

    public BstMap() {
        root = null;
        size = 0;
    }

    @Override
    public void add(K key, V value) {
        this.root = add(this.root, key, value);
    }

    private Node add(Node node, K key, V value) {
        if (node == null) {
            size++;
            return new Node(key, value);
        }

        if (key.compareTo(node.key) < 0) {
            node.left = add(node.left, key, value);
        } else if (key.compareTo(node.key) > 0) {
            node.right = add(node.right, key, value);
        } else {
            node.value = value;
        }

        return node;
    }

    private Node getNode(Node node, K key) {
        if(node == null) return null;

        if (key.compareTo(node.key) == 0) {
            return node;
        } else if (key.compareTo(node.key) < 0) {
            return getNode(node.left, key);
        } else {
            return getNode(node.right, key);
        }
    }

    @Override
    public V remove(K key) {
        return null;
    }

    @Override
    public boolean contains(K key) {
        return getNode(this.root, key) != null;
    }

    @Override
    public V get(K key) {
        Node node = getNode(this.root, key);
        return node != null ? node.value : null;
    }

    @Override
    public void set(K key, V newValue) {
        Node node = getNode(this.root, key);
        if(node == null) throw new IllegalArgumentException("key doesn't exists");

        node.value = newValue;
    }

    @Override
    public int size() {
        return this.size;
    }

    @Override
    public boolean isEmpty() {
        return this.size == 0;
    }

    private class Node {
        public K key;
        public V value;
        public Node left, right;

        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            left = right = null;
        }
    }
}
